var require = globalThis._require;
var sys = require("@native.builtin");
var ntcp = require("@native.tcp");

var EVENT_DATA = "data";
var EVENT_END = "end";
var EVENT_ERROR = "error";
var EVENT_CLOSE = "close";

function createConnection(opt) {
    var ip = opt["ip"];
    var port = opt["port"];
    var success = opt["success"];
    var fail = opt["fail"];

    if (ip == undefined || ip.length == 0 || typeof ip != "string")
        return undefined;

    if (port == undefined || typeof port != "number") return undefined;

    var size = ip.length;
    var host = sys.malloc(size);
    if (host == null) return undefined;
    sys.copy(host, ip, size);

    var fd = ntcp.connect(host, port);
    sys.free(host);

    if (fd < 0) {
        if (typeof fail == "function") {
            fail();
        }
        return undefined;
    }

    if (typeof success == "function") {
        success();
    }

    this.fd = fd;
    this.__id__ = -1;

    this.on = function (event, callback) {
        if(event != EVENT_DATA && event != EVENT_END && event != EVENT_ERROR && event != EVENT_CLOSE)
            return undefined;

        this.__id__ = globalThis.eventbus.on(this, event, callback);
        ntcp.on(this.fd, this.__id__, event);
    };

    this.send = function (opt) {
        var buffer = opt.data;
        if (buffer == undefined || buffer.length == 0) return undefined;
        var size = buffer.length;
        var data = sys.malloc(size);
        if (data == null) return undefined;
        sys.copy(data, buffer, size);
        ntcp.send(this.fd, data, size);
        sys.free(data);
    };

    this.close = function () {
        ntcp.close(this.fd);
        globalThis.eventbus.detach(this);
    };
}

function createClient (opts) {
    return new createConnection(opts);
}

if (globalThis.platform == "nodejs") {
    module.exports = {
        createClient: createClient,
    };
}
